#ifndef BENCHMARK_H
#define BENCHMARK_H

#include <fstream>
#include <iostream>
#include <string>

/**
 * On Liux system, store VM usage (Kb) and RSS usage (Kb) in
 * @param vm_usage and @param resident_set
 * When error occurs, both values will be set as zeroes.
 */
void process_mem_usage(double& vm_usage, double& resident_set) {
  using std::ios_base;
  using std::ifstream;
  using std::string;

  vm_usage = 0.0;
  resident_set = 0.0;

  // 'file' stat seems to give the most reliable results
  //
  ifstream stat_stream("/proc/self/stat", ios_base::in);

  // dummy vars for leading entries in stat that we don't care about
  //
  string pid, comm, state, ppid, pgrp, session, tty_nr;
  string tpgid, flags, minflt, cminflt, majflt, cmajflt;
  string utime, stime, cutime, cstime, priority, nice;
  string O, itrealvalue, starttime;

  // the two fields we want
  //
  unsigned long vsize;
  long rss;

  stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr >>
      tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt >> utime >>
      stime >> cutime >> cstime >> priority >> nice >> O >> itrealvalue >>
      starttime >> vsize >> rss;  // don't care about the rest

  stat_stream.close();

  long page_size_kb = sysconf(_SC_PAGE_SIZE) /
                      1024;  // in case x86-64 is configured to use 2MB pages
  vm_usage = vsize / 1024.0;
  resident_set = rss * page_size_kb;
}

/**
 * Print VM (unit: MB) and RSS (unit: MB) in stderr
 */
void printRss() {
  double vm, rss;

  process_mem_usage(vm, rss);
  fprintf(stderr, "VM = %gMB\tRSS = %gMB\n", vm / 1024.0, rss / 1024.0);
}

#define SHOW_MEM_USAGE(x) \
  do {                    \
    fprintf(stderr, x);   \
    printRss();           \
  } while (0);

#endif /* BENCHMARK_H */
